import {
  getPSUIActionByModelObject,
  IPSAppDataEntity,
  IPSAppDEField,
  IPSAppDERedirectView,
  IPSAppDEUIAction,
  IPSAppDEView,
  IPSAppView,
  IPSAppViewRef,
  IPSNavigateContext,
  IPSNavigateParam,
} from '@ibizstudio/runtime';
import { LogUtil, ModelTool, StringUtil, UIActionTool, Util, ViewTool, AppServiceBase } from '@ibizstudio/runtime';
import { UIServiceRegister } from '@ibizstudio/runtime';
import { Observable, Subject } from 'rxjs';
import { AppGlobalService } from '../app-service';
import { AppPopover, AppModal, AppDrawer, NoticeHandler, appPopup } from '../utils';
import { AppDEUIAction } from './app-ui-action';
import { UIActionResult } from './appuilogic';
import { winMsg } from '../ibz-studio-plugins';
import { notNilEmpty } from 'qx-util';

/**
 * 应用设计前端界面行为
 *
 * @export
 * @class AppDesignFrontAction
 * @extends {AppDEUIAction}
 */
export class AppDesignFrontAction extends AppDEUIAction {
  /**
   * 抽屉打开
   *
   * @type {AppDrawer}
   * @memberof AppDesignFrontAction
   */
  $appdrawer: AppDrawer = AppDrawer.getInstance();

  /**
   * 模态打开
   *
   * @type {AppModal}
   * @memberof AppDesignFrontAction
   */
  $appmodal: AppModal = AppModal.getInstance();

  /**
   * 气泡打开
   *
   * @type {AppPopover}
   * @memberof AppDesignFrontAction
   */
  $apppopover: AppPopover = AppPopover.getInstance();

  /**
   * 路由对象
   *
   * @type {*}
   * @memberof AppDesignFrontAction
   */
  $router: any = AppServiceBase.getInstance().getRouter();

  /**
   * 初始化AppFrontAction
   *
   * @memberof AppFrontAction
   */
  constructor(opts: IPSAppDEUIAction, context?: any) {
    super(opts, context);
  }

  /**
   * 执行界面行为
   *
   * @param {any[]} args
   * @param {*} [context={}]
   * @param {*} [params={}]
   * @param {*} [$event]
   * @param {*} [xData]
   * @param {*} [actionParam]
   * @param {string} [srfParentDeName]
   * @param {*} [deUIService]
   * @return {*}
   * @memberof AppDesignFrontAction
   */
  async execute(args: any[], context: any = {}, params: any = {}, $event?: any, xData?: any, actionParam?: any, srfParentDeName?: string, deUIService?: any) {
    if (Object.is(this.actionModel?.uILogicAttachMode, 'REPLACE')) {
      if (actionParam.context) {
        Object.assign(context, actionParam.context);
      }
      return this.executeDEUILogic(args, context, params, $event, xData, actionParam, srfParentDeName);
    }
    const actionTarget: string | null = this.actionModel.actionTarget;
    if (Object.is(actionTarget, 'MULTIDATA')) {
      NoticeHandler.errorHandler('多数据主键不支持');
    } else {
      // 处理数据
      let data: any = {};
      let tempData: any = {};
      let parentContext: any = {};
      let parentViewParam: any = {};
      if (this.actionModel.saveTargetFirst) {
        const result: any = await xData.save(args, false);
        if (Object.is(actionTarget, 'SINGLEDATA')) {
          Object.assign(args[0], result.data);
        } else {
          args = [result.data];
        }
      }
      const _args: any[] = Util.deepCopy(args);
      if (this.actionModel.getPSAppDataEntity() && (Object.is(actionTarget, 'SINGLEKEY') || Object.is(actionTarget, 'MULTIKEY'))) {
        const entityName = this.actionModel.getPSAppDataEntity()?.codeName.toLowerCase();
        const key = (ModelTool.getAppEntityKeyField(this.actionModel.getPSAppDataEntity()) as IPSAppDEField)?.codeName.toLowerCase();
        const majorKey = (ModelTool.getAppEntityMajorField(this.actionModel.getPSAppDataEntity()) as IPSAppDEField)?.codeName.toLowerCase();
        if (_args[0]?.[key]) {
          Object.assign(context, { [entityName!]: `%${key}%` });
        } else {
          Object.assign(context, { [entityName!]: `%${entityName}%` });
        }
        Object.assign(params, { [key!]: `%${key}%` });
        Object.assign(params, { [majorKey]: `%${majorKey}%` });
      } else if (Object.is(actionTarget, 'SINGLEDATA')) {
        data = args[0];
      }
      // 自定义导航参数优先级大于预置导航参数
      if (this.actionModel.getPSNavigateContexts() && (this.actionModel.getPSNavigateContexts() as IPSNavigateContext[]).length > 0) {
        const localContext = Util.formatNavParam(this.actionModel.getPSNavigateContexts());
        Object.assign(context, localContext);
      }
      if (this.actionModel.getPSNavigateParams() && (this.actionModel.getPSNavigateParams() as IPSNavigateParam[]).length > 0) {
        const localParam = Util.formatNavParam(this.actionModel.getPSNavigateParams());
        Object.assign(params, localParam);
      }
      if (actionParam.context) {
        parentContext = actionParam.context;
      }
      if (actionParam.viewparams) {
        parentViewParam = actionParam.viewparams;
      }
      context = UIActionTool.handleContextParam(actionTarget, _args, parentContext, parentViewParam, context);
      if (Object.is(actionTarget, 'SINGLEDATA')) {
        tempData = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params);
        Object.assign(data, tempData);
      } else {
        data = UIActionTool.handleActionParam(actionTarget, _args, parentContext, parentViewParam, params);
      }
      context = Object.assign({}, actionParam.context, context);
      // 构建srfparentdename和srfparentkey
      let parentObj: any = {
        srfparentdename: srfParentDeName ? srfParentDeName : null,
        srfparentkey: srfParentDeName ? context[srfParentDeName.toLowerCase()] : null,
      };
      Object.assign(data, parentObj);
      Object.assign(context, parentObj);
      const frontPSAppView: IPSAppView | null = this.actionModel.getFrontPSAppView();
      return this.oPenView(frontPSAppView, actionParam, context, args, deUIService, params, $event, data, xData, _args);
    }
  }

  /**
   * 打开视图
   *
   * @param {*} frontPSAppView
   * @param {*} actionParam
   * @param {*} context
   * @param {*} args
   * @param {*} deUIService
   * @param {*} params
   * @param {*} $event
   * @param {*} data
   * @param {*} xData
   * @param {*} _args
   * @return {*}  {Promise<any>}
   * @memberof AppDesignFrontAction
   */
  async oPenView(frontPSAppView: any, actionParam: any, context: any, args: any, deUIService: any, params: any, $event: any, data: any, xData: any, _args: any): Promise<any> {
    return new Promise(async (resolve: any, reject: any) => {
      //打开视图后续逻辑
      const openViewNextLogic: any = async (actionModel: any, actionParam: any, xData: any, resultDatas?: any) => {
        if (actionModel.reloadData && xData && xData.refresh && xData.refresh instanceof Function) {
          if (args && args.length > 0) {
            Object.assign(args[0], { refreshMode: actionModel.refreshMode });
          } else {
            args.push({ refreshMode: actionModel.refreshMode });
          }
          xData.refresh(args);
        }
        if (actionModel.closeEditView) {
          actionParam.closeView(null);
        }
        // 后续界面行为
        if (this.actionModel.M?.getNextPSUIAction) {
          const nextUIaction: any = await getPSUIActionByModelObject(this.actionModel);
          if (nextUIaction.getPSAppDataEntity()) {
            let [tag, appDeName] = (nextUIaction as IPSAppDEUIAction).id.split('@');
            const UIService = await UIServiceRegister.getService(actionParam.context, `${appDeName.toLowerCase()}`);
            await UIService.loaded();
            if (UIService) {
              return UIService.excuteAction(tag, resultDatas, context, params, $event, xData, actionParam, undefined, UIService);
            }
          } else {
            return (AppGlobalService.getInstance() as any).executeGlobalAction(nextUIaction.id, resultDatas, context, params, $event, xData, actionParam, undefined);
          }
        } else {
          if (Object.is(actionModel?.uILogicAttachMode, 'AFTER')) {
            if (actionParam.context) {
              Object.assign(context, actionParam.context);
            }
            return this.executeDEUILogic(args, context, params, $event, xData, actionParam, context?.srfparentdename);
          } else {
            return new UIActionResult({ ok: true, result: resultDatas });
          }
        }
      };
      if (Object.is(this.actionModel.frontProcessType, 'OPENHTMLPAGE') && this.actionModel.htmlPageUrl) {
        const url = StringUtil.fillStrData(this.actionModel.htmlPageUrl, context, data);
        window.open(url, '_blank');
        resolve(new UIActionResult({ ok: true, result: data }));
        // 打开顶级视图，打开顶级视图或向导（模态）
      } else if (Object.is(this.actionModel.frontProcessType, 'TOP') || Object.is(this.actionModel.frontProcessType, 'WIZARD')) {
        if (!this.actionModel.getFrontPSAppView()) {
          NoticeHandler.warningHandler(`${this.actionModel.caption} 无打开视图`);
          return;
        }
        await frontPSAppView?.fill(true);
        if (!frontPSAppView) {
          return;
        }
        // 准备deResParameters参数和parameters参数
        let deResParameters: any[] = [];
        let parameters: any[] = [];
        if (frontPSAppView.getPSAppDataEntity()) {
          // 处理视图关系参数 （只是路由打开模式才计算）
          if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB' || frontPSAppView.openMode == 'POPUPAPP') {
            deResParameters = Util.formatAppDERSPath(context, (frontPSAppView as IPSAppDEView).getPSAppDERSPaths());
          }
        }
        if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB' || frontPSAppView.openMode == 'POPUPAPP') {
          if (frontPSAppView.getPSAppDataEntity()) {
            parameters = [
              {
                pathName: Util.srfpluralize((frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName).toLowerCase(),
                parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(),
              },
              {
                pathName: 'views',
                parameterName: ((frontPSAppView as IPSAppDEView).getPSDEViewCodeName() as string).toLowerCase(),
              },
            ];
          } else {
            parameters = [{ pathName: 'views', parameterName: frontPSAppView.codeName.toLowerCase() }];
          }
        } else {
          if (frontPSAppView.getPSAppDataEntity()) {
            parameters = [
              {
                pathName: Util.srfpluralize((frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName).toLowerCase(),
                parameterName: (frontPSAppView.getPSAppDataEntity() as IPSAppDataEntity)?.codeName.toLowerCase(),
              },
            ];
          }
          if (frontPSAppView && frontPSAppView.modelPath) {
            Object.assign(context, { viewpath: frontPSAppView.modelPath });
          }
        }
        // 打开重定向视图
        if (frontPSAppView.redirectView) {
          const data = args[0];
          const field: IPSAppDEField | null = (frontPSAppView as IPSAppDERedirectView).getTypePSAppDEField();
          if (frontPSAppView.codeName === 'PSSysAppLinkRedirectView') {
            const type = context.linktype;
            if (notNilEmpty(type)) {
              winMsg.openView(type, context, params, [data]);
            } else {
              console.warn(`未找到对应重定向类型 ${type} ，暂时无法打开iframe级别视图跳转!`);
            }
            return;
          }
          if (field) {
            const type = data[field.codeName.toLocaleLowerCase()];
            const appViewRefs = (frontPSAppView as IPSAppDERedirectView).getRedirectPSAppViewRefs()!;
            let appViewRef: IPSAppViewRef | undefined = appViewRefs?.find((appViewRef: IPSAppViewRef) => appViewRef.name === type || appViewRef.name === `EDITVIEW:${type}`);
            if (!appViewRef) {
              appViewRef = appViewRefs?.find((appViewRef: IPSAppViewRef) => {
                const entityName = frontPSAppView.getPSAppDataEntity()?.name;
                return appViewRef.name === type || appViewRef.name === `${entityName}:EDITVIEW:${type}`;
              });
            }
            if (appViewRef) {
              const appView: any = await appViewRef.getRefPSAppView()?.fill();
              const localContext = Util.formatNavParam(appViewRef.getPSNavigateContexts());
              for (let key in localContext) {
                localContext[key] = StringUtil.fillStrData(localContext[key], context);
              }
              Object.assign(context, localContext);
              return this.oPenView(appView, actionParam, context, args, deUIService, params, $event, data, xData, _args);
            }
          }
        } else if (!frontPSAppView.openMode || frontPSAppView.openMode == 'INDEXVIEWTAB') {
          const routePath = ViewTool.buildUpRoutePath(this.$router.currentRoute, context, deResParameters, parameters, _args, data);
          this.$router.push(routePath);
          resolve(openViewNextLogic(this.actionModel, actionParam, xData, data));
        } else if (frontPSAppView.openMode == 'POPUPAPP') {
          const routePath = ViewTool.buildUpRoutePath(this.$router.currentRoute, context, deResParameters, parameters, _args, data);
          window.open('./#' + routePath, '_blank');
          resolve(openViewNextLogic(this.actionModel, actionParam, xData, data));
        } else if (frontPSAppView.openMode == 'POPUPMODAL') {
          const view: any = {
            viewname: 'app-view-shell',
            height: frontPSAppView.height,
            width: frontPSAppView.width,
            title: frontPSAppView.caption,
          };
          let container: Subject<any> = this.$appmodal.openModal(view, context, data, args);
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas));
          });
        } else if (frontPSAppView.openMode?.indexOf('DRAWER') !== -1) {
          const view: any = {
            viewname: 'app-view-shell',
            height: frontPSAppView.height,
            width: frontPSAppView.width,
            title: frontPSAppView.caption,
            placement: frontPSAppView.openMode,
          };
          let container: Subject<any> = this.$appdrawer.openDrawer(view, Util.getViewProps(context, data, args));
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas));
          });
        } else if (frontPSAppView.openMode === 'POPUP') {
          const view: any = {
            viewname: 'app-view-shell',
            height: frontPSAppView.height,
            width: frontPSAppView.width,
            title: frontPSAppView.caption,
            placement: frontPSAppView.openMode,
          };
          const container = appPopup.openDrawer(view, Util.getViewProps(context, data, args));
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas));
          });
        } else if (frontPSAppView.openMode == 'POPOVER') {
          const view: any = {
            viewname: 'app-view-shell',
            height: frontPSAppView.height,
            width: frontPSAppView.width,
            title: frontPSAppView.caption,
            placement: frontPSAppView.openMode,
          };
          let container: Observable<any> = this.$apppopover.openPop($event, view, context, data, 'left-end', true, args);
          container.subscribe((result: any) => {
            if (!result || !Object.is(result.ret, 'OK')) {
              return;
            }
            resolve(openViewNextLogic(this.actionModel, actionParam, xData, result.datas));
          });
        } else {
          NoticeHandler.warningHandler(`${frontPSAppView.title} 不支持该模式打开`);
        }
        // 用户自定义
      } else {
        LogUtil.warn(`${this.actionModel.caption}自定义界面行为空执行`);
        resolve(openViewNextLogic(this.actionModel, actionParam, xData, data));
      }
    });
  }
}
